
#include "../include/Dlt645MessageManager.h"
#include "../include/dlt645def.h"
#include "../include/Dlt645Frame.h"
#include "../include/Dlt645ParseTask.h"
#include "../include/Dlt645FrozenDataParseTask.h"
#include "../../common/include/common.h"
#include "../../common/include/hex.h"

#include "../../db/include/CDBManager.h"
#include "CLogger.h"

#include <string.h>
#include <sstream>
#include <typeinfo>

CDlt645MessageManager CDlt645MessageManager::m_dlt645mm;

CDlt645MessageManager::CDlt645MessageManager(){
    m_thread_pool.init(3);
    c_req_id = 0;
}

CDlt645MessageManager::~CDlt645MessageManager(){
    m_thread_pool.destory();

}


CDlt645MessageManager &CDlt645MessageManager::getInstance(){
    return m_dlt645mm;
}

int CDlt645MessageManager::run(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm, IModule &im, TASK_PARAMS *pdev_task)
{
    if ((nullptr == pcm) || (nullptr == channel_ptr) || (nullptr == pmm) || (nullptr == pdev_task))
    {
        return -1;
    }
    c_im = im;
    m_pdev_task = pdev_task;

    CLogger::getInstance()->log_d("645MessageManager:request item num =%d", pdev_task->items.size());


    switch (pdev_task->type)
    {
    case TASK_TYPE_COLLECT:
        run_collect(pcm, channel_ptr, pmm, pdev_task);
        break;
    case TASK_TYPE_CTL_CMD_RULE:
    case TASK_TYPE_SET_CMD_RULE:
    case TASK_TYPE_LINKAGE:
        run_ctrl_cmd(pcm, channel_ptr, pdev_task);
        break;
    case TASK_TYPE_GET_CMD_RULE:
        run_read_cmd(pcm, channel_ptr, pmm, pdev_task);
        break;
    case TASK_TYPE_FROZEN_COLLECT:
        run_frozen_collect(pcm, channel_ptr, pmm, m_pdev_task);
        break;
    default:
        CLogger::getInstance()->LOG_W("The task type(%d) not surport.", pdev_task->type);
        break;
    }

    return 0;
}

int CDlt645MessageManager::run_collect(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm, TASK_PARAMS *pdev_task)
{
    auto dev = pcm->get_terminal_device(pdev_task->dev_id);
    if (nullptr == dev){
        CLogger::getInstance()->LOG_W("不存在该设备:%lld", pdev_task->dev_id);
        return -1;
    }

    for (auto taskitem = pdev_task->items.begin(); taskitem != pdev_task->items.end(); taskitem++)
    {
        auto task_item = pcm->get_item(taskitem->item_id);
        if (nullptr == task_item){
            CLogger::getInstance()->LOG_W("不存在该任务项:%lld", taskitem->item_id);
            continue;
        }

        auto dl645_req = pcm->get_dlt645_request(task_item->task_item_id);
        if (nullptr == dl645_req)
        {
            CLogger::getInstance()->LOG_W("不存在该请求项:%lld", taskitem->item_id);
            continue;
        }

        std::list<std::shared_ptr<ST_DL645_RSPDATA>> lst_rspdata;
        std::shared_ptr<ST_DL645_RSPDATA> pdlt645_rspdata = std::make_shared<ST_DL645_RSPDATA>();
        pdlt645_rspdata->di = dl645_req->di;
        pdlt645_rspdata->dev_id = dev->id;
        pdlt645_rspdata->protocol_id = dl645_req->protocol_id;

        CLogger::getInstance()->log_d("dlt645 run devid=%lld,task_item_id=%lld,di=%s", dev->id, task_item->task_item_id, dl645_req->di.c_str());

        if (0 == run_req_taskitem(pcm, channel_ptr, dev, pdev_task->task_id, task_item->task_item_id, pdlt645_rspdata))
        {
            lst_rspdata.push_back(pdlt645_rspdata);
        }
        else{
            continue;
        }

        //粗解析数据，判断有无后续数据，若有，循环读取后续数据
        if (ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == get_ctrlcode(pdlt645_rspdata->pdata, pdlt645_rspdata->datalen))
        {
            run_req_get_subseqdata(lst_rspdata, dev->id, dl645_req->di, dl645_req->protocol_id, pcm, channel_ptr, dev, pdev_task->task_id);
        }

        //添加到解析任务线程池
        if (0 < lst_rspdata.size())
        {
            CDlt645ParseTask *pdlt645_parsetask = new CDlt645ParseTask(pcm, pmm, pdev_task, lst_rspdata);
            if (pdlt645_parsetask)
            {
                m_thread_pool.add_task(pdlt645_parsetask);
            }
        }
    }

    return 0;
}

int CDlt645MessageManager::run_ctrl_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, TASK_PARAMS *pdev_task)
{
    auto dev = pcm->get_terminal_device(pdev_task->dev_id);
    if (nullptr == dev){
        CLogger::getInstance()->log_w("the device not exit:%lld", pdev_task->dev_id);
        return -1;
    }

    for (auto taskitem = pdev_task->items.begin(); taskitem != pdev_task->items.end(); taskitem++)
    {
        auto protocol_rule = pcm->get_protocol_rule(dev->protocol_id);
        if (2 == protocol_rule->protocol_type)
        {
            run_dlt645_ctrl_cmd(pcm, channel_ptr, taskitem->item_id, dev, pdev_task);
        }
        else{
            CLogger::getInstance()->log_w("the protocol_rule=%d not surport.", protocol_rule->protocol_type);
        }

    }

    return 0;
}

int CDlt645MessageManager::run_dlt645_ctrl_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, int64_t task_item_id, std::shared_ptr<TERMINAL_DEVICE> dev, TASK_PARAMS *pdev_task)
{
    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[8] = { 0 };
    uint8_t ucpwd[8] = { 0 };
    uint8_t ucoprcode[8] = { 0 };
    uint8_t ucdata[32] = { 0 };
    uint8_t bytedata[32] = { 0 };
    uint8_t ucFrameData[256] = { 0 };
    uint8_t ucrsp[64] = { 0 };

    int addr_len = 0, di_len = 0, frm_len = 0, rsp_len = 0;
    int pwd_len = 0, oprcode_len = 0, data_len = 0;

    auto dlt645cmd = pcm->get_dlt645_command(task_item_id);
    if (nullptr == dlt645cmd)
    {
        CLogger::getInstance()->log_w("run_dlt645_ctrl_cmd:not find ctrl cmd.");
        return -1;
    }

    auto proto = pcm->get_protocol_rule(dlt645cmd->protocol_id);
    if(nullptr == proto){
        return -1;
    }

    CLogger::getInstance()->log_d("run_dlt645_ctrl_cmd: slave_addr:%s,funcode=0x%02x,di=%s", dev->slave_addr.c_str(), dlt645cmd->func_code, dlt645cmd->di.c_str());

    slave_addr_tobcd(dev->slave_addr, ucaddr, addr_len);
    string_tobcd(dlt645cmd->di, ucdi, di_len);

    if ((6 > addr_len) || (4 > di_len))
    {
        CLogger::getInstance()->log_w("run_dlt645_ctrl_cmd:the dlt645 meteraddr or di error.");
        return -1;
    }

    std::unordered_map<std::string, RESPONSE_DATA> resp_datas;
    for (auto task_item = pdev_task->items.begin(); task_item != pdev_task->items.end(); task_item++)
    {
        CLogger::getInstance()->log_d("run_dlt645_ctrl_cmd: setval=%s", task_item->value.c_str());

        std::string  cmd_val = task_item->value;
        if (pdev_task->type == TASK_TYPE_LINKAGE){
            cmd_val = dlt645cmd->def_value;
        }
        if (!cmd_val.empty())
        {
            std::string  strval = get_final_value(dlt645cmd, cmd_val);
            CLogger::getInstance()->log_d("run_dlt645_ctrl_cmd: get_final_value=%s", strval.c_str());
            if (ENUM_645_ENCODE_BCD == dlt645cmd->coding_type)
            {
                double fbcd = std::stod(strval);
                if (dlt645cmd->decimal > 0){
                    for (int i = 0; i < dlt645cmd->decimal; i++){
                        fbcd *= 10.0;
                    }
                }

                char bcd_fmt[16] = { 0 };
                char fmt_data[16] = { 0 };
                snprintf(bcd_fmt, sizeof(bcd_fmt), "%%0%d.0lf", dlt645cmd->data_size * 2);
                snprintf(fmt_data, sizeof(fmt_data), bcd_fmt, fbcd);

                std::string strbcd(fmt_data);
                CLogger::getInstance()->log_d("run_dlt645_ctrl_cmd: fmt getfinal=%s", strbcd.c_str());
                string_tobcd(strbcd, bytedata, data_len);
            }
            else{
                data_len = get_hexwrt_data(dlt645cmd, strval, ucdata);
                //字节序转换
                if (dlt645cmd->byte_order == ENUM_645HEX_ORDER_LITTLE_ENDIAN)
                {
                    for (int i = 0; i < data_len; i++)
                    {
                        bytedata[i] = ucdata[i];
                    }
                }
                else if (dlt645cmd->byte_order == ENUM_546HEX_ORDER_BIG_ENDIAN){
                    for (int i = 0; i < data_len; i++)
                    {
                        bytedata[i] = ucdata[data_len - 1 - i];
                    }
                }
            }
        }

        int ret = 0;
        uint8_t ctrl_code = dlt645cmd->func_code;
        //if (ENUM_CTRLCODE_WRITE_DATA == ctrl_code)
        {
            if (!dlt645cmd->passwd.empty()){
                std::string strpass = dlt645cmd->passwd;
                /*if (dlt645cmd->passwd.length() <8) {
                    for (int i = 0; i < 8 - dlt645cmd->passwd.length(); i++) {
                    strpass = "0" + strpass;
                    }
                    }*/
                string_tobcd(strpass, ucpwd, pwd_len);
            }
            if (!dlt645cmd->oprcode.empty())
            {
                std::string strcode = dlt645cmd->oprcode;
                /*if (dlt645cmd->oprcode.length() < 4) {
                    for (int i = 0; i < 4 - dlt645cmd->oprcode.length(); i++) {
                    strcode = "00" + strcode;
                    }
                    }*/
                string_tobcd(strcode, ucoprcode, oprcode_len);
            }

            st_dlt645_wrtdata_items  dlt645_wrtdata;
            dlt645_wrtdata.ctrlcode = ctrl_code;
            memcpy(dlt645_wrtdata.szDataFlag, ucdi, 4);
            memcpy(dlt645_wrtdata.szMeterAddr, ucaddr, 6);
            memcpy(dlt645_wrtdata.szOprCode, ucoprcode, 4);
            memcpy(dlt645_wrtdata.szPasswd, ucpwd, 4);
            dlt645_wrtdata.oprcode_len = oprcode_len;
            dlt645_wrtdata.pwd_len = pwd_len;
            dlt645_wrtdata.datalen = data_len;
            memcpy(dlt645_wrtdata.frmData, bytedata, data_len);

            ret = CDlt645Frame::getIntanse()->packet_writedata_req(dlt645_wrtdata, ucFrameData, frm_len);
        }

        if (ret > 0)
        {
            CLogger::getInstance()->log_d("run_dlt645_ctrl_cmd send data(len=%d):", frm_len);
            OutputInfo(ucFrameData, frm_len, true, pdev_task->dev_id);
            rsp_len = DLT645_FRMDATA_LEN; //最大响应长度
            channel_ptr->set_slave_addr(dev->slave_addr);
            channel_ptr->send_msg(ucFrameData, frm_len, ucrsp, rsp_len, proto->timeout);

            RESPONSE_DATA resp_data;
            if ((rsp_len > 0) && (rsp_len != DLT645_FRMDATA_LEN) ){
                uint8_t rsp_code = get_ctrlcode(ucrsp, rsp_len);
                if (rsp_code < 0xD1)   //返回控制码正常情况0x91~0x9E,大于0xD1属异常
                {
                    resp_data.msg = "命令执行成功";
                    resp_data.code = 0;
                }
                else {
                    resp_data.msg = "命令执行失败";
                    resp_data.code = -1;
                }

                //保存命令响应信息
                resp_data.name = dev->name;
                resp_data.value = "";
                resp_datas.insert(std::make_pair(dlt645cmd->name, resp_data));
            }
            else{
                CLogger::getInstance()->log_w("SerialProxy send data timeout.");
            }
            
            //上报命令执行结果
            if (TASK_TYPE_SET_CMD_RULE == pdev_task->type){
                if (0 > pdev_task->req_id){
                    pdev_task->req_id = get_req_id();
                }
                if (resp_datas.empty()){
                    CReportManager::getInstance().cmd_response(pdev_task->dev_id, pdev_task->req_id, "CMD_SET_COMMAND_RULE", -1, "命令未执行");
                }
                else {
                    CReportManager::getInstance().cmd_response(pdev_task->dev_id, pdev_task->req_id, "CMD_SET_COMMAND_RULE", resp_datas.begin()->second.code, resp_datas.begin()->second.msg);
                }
            }
        }
    }


    return 0;
}

int64_t CDlt645MessageManager::get_req_id(){
    std::lock_guard<std::mutex> lock(c_mutex);
    c_req_id++;
    if (0 > c_req_id){
        c_req_id = 0;
    }
    return c_req_id;
}
int CDlt645MessageManager::run_req_taskitem(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr,
    std::shared_ptr<TERMINAL_DEVICE> dev, int64_t task_id,
    int64_t task_item_id, std::shared_ptr<ST_DL645_RSPDATA> rsp_data)
{

    auto dlt645_req = pcm->get_dlt645_request(task_item_id);
    if (nullptr == dlt645_req)
    {
        CLogger::getInstance()->log_w("The dlt645 request(id=%lld) not exit.", task_item_id);
        return -1;
    }

    auto proto = pcm->get_protocol_rule(dlt645_req->protocol_id);
    if(nullptr == proto){
        return -1;
    }

    CLogger::getInstance()->log_d("run_req_taskitem:task_itemid=%lld, di=%s", task_item_id, rsp_data->di.c_str());

    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[16] = { 0 };
    int addr_len = 0, di_len = 0, frm_len = 0, rsp_len = 0;
    slave_addr_tobcd(dev->slave_addr, ucaddr, addr_len);
    string_tobcd(rsp_data->di, ucdi, di_len);


    if ((6 > addr_len) || (4 > di_len))
    {
        CLogger::getInstance()->LOG_W("The dlt645 meteraddr or di error.");
        return -1;
    }

    memcpy(rsp_data->meter_addr, ucaddr, 6);
    CDlt645Frame::getIntanse()->packet_readingdata_req(ucaddr, ucdi, m_pdata, frm_len);
    if (frm_len > 0)
    {
        rsp_len = DLT645_FRMDATA_LEN;  //  >dlt645最大帧长
        channel_ptr->set_slave_addr(dev->slave_addr);
        channel_ptr->send_msg(m_pdata, frm_len, m_prspdata, rsp_len, proto->timeout); 
        OutputInfo(m_pdata, frm_len, true, dev->id);
        if ((rsp_len > 0) && (DLT645_FRMDATA_LEN != rsp_len))
        {
            rsp_data->datalen = rsp_len;
            rsp_data->pdata = new uint8_t[rsp_len];
            if (rsp_data->pdata) {
                memcpy(rsp_data->pdata, m_prspdata, rsp_len);
            }
            else{
                CLogger::getInstance()->LOG_E("new data pointer error.");
            }
            save_interaction_log(rsp_data->dev_id, task_id, m_pdata, frm_len, m_prspdata, rsp_len);

            OutputInfo(m_prspdata, rsp_len, false, dev->id);
        }
        else{
            CLogger::getInstance()->LOG_W("run_req_taskitem: recv data is null.");
            return -1;
        }
    }

    return 0;
}

int CDlt645MessageManager::run_req_get_subseqdata(std::list<std::shared_ptr<ST_DL645_RSPDATA>> &lst_rspdata, int64_t dev_id,
    const std::string& di, int64_t rule_id, std::shared_ptr<CConfigManager> pcm,
    IChannel *channel_ptr, std::shared_ptr<TERMINAL_DEVICE> dev, int64_t task_id)
{
    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[8] = { 0 };
    int addr_len = 0, di_len = 0, frm_len = 0, rsp_len = 0;
    auto proto = pcm->get_protocol_rule(rule_id);
    if(nullptr == proto){
        return -1;
    }
    slave_addr_tobcd(dev->slave_addr, ucaddr, addr_len);
    string_tobcd(di, ucdi, di_len);

    if ((6 > addr_len) || (4 > di_len))
    {
        CLogger::getInstance()->LOG_W("The dlt645 meteraddr or di error.");
        return -1;
    }

    uint8_t ctrl_code = 0;
    uint8_t seq_id = 1;
    while (seq_id <= 255) // 帧号最大255
    {
        frm_len = 0;
        CDlt645Frame::getIntanse()->packet_readingsubseqdata_req(ucaddr, ucdi, seq_id, m_pdata, frm_len);
        if (frm_len > 0)
        {
            rsp_len = DLT645_FRMDATA_LEN;  //  >645最大帧长
            channel_ptr->set_slave_addr(dev->slave_addr);
            channel_ptr->send_msg(m_pdata, frm_len, m_prspdata, rsp_len, proto->timeout);
            OutputInfo(m_pdata, frm_len, true, dev->id);
            if ((rsp_len > 0) && (DLT645_FRMDATA_LEN != rsp_len))
            {
                OutputInfo(m_prspdata, rsp_len, false, dev->id);
                std::shared_ptr<ST_DL645_RSPDATA> rsp_data = std::make_shared<ST_DL645_RSPDATA>();

                rsp_data->dev_id = dev_id;
                rsp_data->protocol_id = rule_id;
                rsp_data->di = di;
                rsp_data->datalen = rsp_len;
                memcpy(rsp_data->meter_addr, ucaddr, 6);
                rsp_data->pdata = new uint8_t[rsp_len];
                if (rsp_data->pdata)  {
                    memcpy(rsp_data->pdata, m_prspdata, rsp_len);
                    lst_rspdata.push_back(rsp_data);
                }
                else{
                    CLogger::getInstance()->LOG_E("run_req_get_subseqdata:new data pointer error.");
                }
                save_interaction_log(dev_id, task_id, m_pdata, frm_len, m_prspdata, rsp_len);

                ctrl_code = get_ctrlcode(m_prspdata, rsp_len);
                if (ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP == ctrl_code)
                {
                    seq_id++;
                }
                else if (ENUM_CTRLCODE_READ_SUBSEQDATA_RSP == ctrl_code)
                {
                    break;  //无后续数据，退出
                }
            }
            else{
                CLogger::getInstance()->LOG_W("run_req_get_subseqdata:Proxy recv data is null.");
                return -1;
            }
        }
    }

    return 0;
}

//保存交互日志
void CDlt645MessageManager::save_interaction_log(int64_t dev_id, int64_t task_id, uint8_t *req, int req_len, uint8_t *rsp, int rsp_len)
{
    if ((nullptr == req) || (nullptr == rsp))
    {
        return;
    }

    DEV_INTERACTIVE_MSG interfacive_msg;
    interfacive_msg.dev_id = dev_id;

    INTERACTIVE_MESSAGE msg;
    msg.id = -1;
    msg.task_id = task_id;
    msg.execution_time = get_timestamp();

    memset(m_pstr, 0, TEMP_STR_LEN);
    int buf_len = 0;
    if (0 == hex_to_str(req, req_len, m_pstr, &buf_len)){
        msg.direction = INITIATE_REQUEST;
        msg.content = m_pstr;
        interfacive_msg.msgs.push_back(msg);
    }
    memset(m_pstr, 0, TEMP_STR_LEN);
    if (0 == hex_to_str(rsp, rsp_len, m_pstr, &buf_len)){
        msg.direction = INITIATE_RESPONSE;
        msg.content = m_pstr;
        interfacive_msg.msgs.push_back(msg);
    }

    CDBManager::getInstance()->insert_log(interfacive_msg);
}

//将数字字符串转换位BCD码
int CDlt645MessageManager::string_tobcd(const std::string& strdi, uint8_t* pbcd, int& len)
{
    if ((0 == strdi.length()) || (nullptr == pbcd)) {
        return 0;
    }

    memset(m_pstr, 0, TEMP_STR_LEN);
    int strlen = strdi.length() < TEMP_STR_LEN ? strdi.length() : TEMP_STR_LEN;
    strncpy(m_pstr, strdi.c_str(), strlen);

    for (int i = 0; i < strlen; i = i + 2){
        pbcd[i / 2] = ascii_to_decim(m_pstr[i]) * 16 + ascii_to_decim(m_pstr[i + 1]);
    }

    len = strlen / 2;
    return len;
}

char CDlt645MessageManager::ascii_to_decim(char ch)
{
    char decim = 0;
    if ((ch >= 0x30) && (ch <= 0x39)){   //char '0' -'9'
        decim = ch - 0x30;
    }
    else if ((ch >= 0x41) && (ch <= 0x46)){  //char 'A' -'F'
        decim = ch - 55;
    }
    else if ((ch >= 0x61) && (ch <= 0x66)){  //char 'a' -'f'
        decim = ch - 87;
    }

    return decim;
}

//获取控制吗，若帧错误返回0
uint8_t CDlt645MessageManager::get_ctrlcode(uint8_t* pdata, int len)
{
    uint8_t ctrlcode = 0;
    int prefix_num = verify_dlt645_frame(pdata, len);

    if (prefix_num < 0)
    {
        return ctrlcode;
    }

    ctrlcode = pdata[prefix_num + 8];

    return ctrlcode;
}

//dlt645帧校验，正确是返回前导符个数，错误返回 <0
int  CDlt645MessageManager::verify_dlt645_frame(uint8_t* pdata, int len)
{
    int prefix_num = 0;
    if ((MIN_FRAME_LEN > len) || (!pdata))
    {
        return -1;
    }

    for (int i = 0; i < 4; i++) {
        if (CHR_PREFIX == pdata[i])
        {
            prefix_num++;
        }
    }
    if ((CHR_FRMSTART != pdata[prefix_num]) || (CHR_FRMSTART != pdata[prefix_num + 7]))
    {
        return -2;
    }

    return prefix_num;
}

void CDlt645MessageManager::OutputInfo(uint8_t* pData, int len, bool bsend/* =true */, int64_t dev_id/*=0*/)
{
    char  szch[8] = { 0 };
    int info_len = len < DLT645_FRMDATA_LEN ? len : DLT645_FRMDATA_LEN;
    for (int i = 0; i < info_len; i++){
        sprintf(szch, "%02X ", pData[i]);
        strcat(m_szinfo, szch);
    }

    if (bsend){
        CLogger::getInstance()->LOG_I("dlt645 devid=%lld,send data:%s", dev_id, m_szinfo);
    }
    else{
        CLogger::getInstance()->LOG_I("dlt645 devid=%lld,recv data:%s", dev_id, m_szinfo);
    }
    memset(m_szinfo, 0, sizeof(m_szinfo));
}

int CDlt645MessageManager::run_read_cmd(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr, std::shared_ptr<CMosquittoManager> pmm, TASK_PARAMS *pdev_task)
{
    if ((NULL == pcm) || (nullptr == pdev_task)) {
        return -1;
    }

    auto dev = pcm->get_terminal_device(pdev_task->dev_id);
    if (nullptr == dev){
        CLogger::getInstance()->LOG_W("CDlt645MessageManager::run_read_cmd,不存在该设备:%lld", pdev_task->dev_id);
        return -1;
    }

    std::list<std::shared_ptr<ST_DL645_RSPDATA>> lst_rspdata;
    for (auto item = pdev_task->items.begin(); item != pdev_task->items.end(); item++)
    {
        read_dlt645cmd_hangler(pcm, pmm, dev, channel_ptr, item->item_id, pdev_task, lst_rspdata);
    }

    //添加到645解析任务线程池
    if (0 < lst_rspdata.size())
    {

        CDlt645ParseTask *pdlt645_parsetask = new CDlt645ParseTask(pcm, pmm, pdev_task, lst_rspdata);
        if (pdlt645_parsetask)
        {
            m_thread_pool.add_task(pdlt645_parsetask);
        }
    }

    return 0;
}

int CDlt645MessageManager::read_dlt645cmd_hangler(std::shared_ptr<CConfigManager> pcm, std::shared_ptr<CMosquittoManager> pmm,
    std::shared_ptr<TERMINAL_DEVICE> dev, IChannel *channel_ptr, int64_t task_item_id, TASK_PARAMS *pdev_task,
    std::list<std::shared_ptr<ST_DL645_RSPDATA>>& lst_rspdata)
{

    auto dl645_point = pcm->get_dlt645_point(task_item_id);
    if (nullptr == dl645_point)
    {
        CLogger::getInstance()->LOG_W("read_dlt645cmd_hangler:不存在该命令点:%lld", task_item_id);
        return -1;
    }

    std::shared_ptr<ST_DL645_RSPDATA> pdlt645_rspdata = std::make_shared<ST_DL645_RSPDATA>();
    pdlt645_rspdata->di = dl645_point->di;
    pdlt645_rspdata->dev_id = dev->id;
    pdlt645_rspdata->protocol_id = dl645_point->protocol_id;

    CLogger::getInstance()->log_i("CDlt645MessageManager::read_dlt645cmd_hangler,start run reqtask.");
    if (0 == run_req_taskitem(pcm, channel_ptr, dev, pdev_task->task_id, task_item_id, pdlt645_rspdata))
    {
        lst_rspdata.push_back(pdlt645_rspdata);
    }
    else{
        return -1;
    }

    //粗解析数据，判断有无后续数据，若有，循环读取后续数据
    if (ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == get_ctrlcode(pdlt645_rspdata->pdata, pdlt645_rspdata->datalen))
    {
        run_req_get_subseqdata(lst_rspdata, dev->id, dl645_point->di, dl645_point->protocol_id, pcm, channel_ptr, dev, pdev_task->task_id);
    }


    return 0;
}

std::string CDlt645MessageManager::get_final_value(std::shared_ptr<DLT645_COMMAND> dlt645cmd, std::string val)
{
    std::string final_val;
    if (nullptr == dlt645cmd){
        return final_val;
    }

    double set_val = std::stod(val);
    double v = 0;
    char ret_buf[64] = { 0 };
    char str_format[32] = { 0 };
    if (dlt645cmd->formula.empty()){
        v = set_val * dlt645cmd->scale;
    }
    else {
        std::string formula = "echo \"" + dlt645cmd->formula + "\"|bc";
        std::stringstream fstr;
        fstr << val;

        formula = string_replace(formula, "X", fstr.str());
        if (0 == exec_cmd((char *)formula.c_str(), ret_buf, sizeof(ret_buf))){
            v = std::stod(ret_buf);
        }
    }
    if (0 < dlt645cmd->decimal){
        snprintf(str_format, sizeof(str_format), "%%.%dlf", dlt645cmd->decimal);
        snprintf(ret_buf, sizeof(ret_buf), str_format, v);
    }
    else {
        snprintf(ret_buf, sizeof(ret_buf), "%lf", v);
    }

    final_val = std::string(ret_buf);

    return final_val;
}

int CDlt645MessageManager::get_hexwrt_data(std::shared_ptr<DLT645_COMMAND> dlt645cmd, std::string final_val, uint8_t* pdata)
{
    if (nullptr == pdata){
        return 0;
    }

    int data_len = 0;
    switch (dlt645cmd->data_type)
    {
    case ENUM_645_DATATYPE_CHAR:
    {
        char cval = (char)std::stoi(final_val);
        pdata[0] = cval;
        data_len = 1;
        break;
    }
    case ENUM_645_DATATYPE_UNSIGNED_CHAR:
    {
        uint8_t ucval = (uint8_t)std::stoi(final_val);
        pdata[0] = ucval;
        data_len = 1;
        break;
    }
    case ENUM_645_DATATYPE_SHORT:
    {
        int16_t  sval = (int16_t)std::stoi(final_val);
        memcpy(pdata, &sval, sizeof(int16_t));
        data_len = 2;
        break;
    }
    case ENUM_645_DATATYPE_UNSIGNED_SHORT:
    {
        uint16_t usval = (int16_t)std::stoi(final_val);
        memcpy(pdata, &usval, sizeof(uint16_t));
        data_len = 2;
        break;
    }
    case ENUM_645_DATATYPE_INT:
    {
        int32_t ival = std::stoi(final_val);
        memcpy(pdata, &ival, sizeof(int32_t));
        data_len = 4;
        break;
    }
    case ENUM_645_DATATYPE_UNSIGNED_INT:
    {
        uint32_t uival = (uint32_t)std::stoul(final_val);
        memcpy(pdata, &uival, sizeof(uint32_t));
        data_len = 4;
        break;
    }
    case ENUM_645_DATATYPE_FLOAT:
    {
        float fval = std::stof(final_val);
        memcpy(pdata, &fval, sizeof(float));
        data_len = 4;
        break;
    }
    case ENUM_645_DATATYPE_INT64:
    {
        int64_t llval = std::stoll(final_val);
        memcpy(pdata, &llval, sizeof(int64_t));
        data_len = 8;
        break;
    }
    case ENUM_645_DATATYPE_UNSIGNED_INT64:
    {
        uint64_t ullval = std::stoull(final_val);
        memcpy(pdata, &ullval, sizeof(uint64_t));
        data_len = 8;
        break;
    }
    case ENUM_645_DATATYPE_DOUBLE:
    {
        double dfval = std::stod(final_val);
        memcpy(pdata, &dfval, sizeof(double));
        data_len = 8;
        break;
    }
    default:
        break;
    }

    return data_len;
}

//冻结数据抄读入口
int CDlt645MessageManager::run_frozen_collect(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr,
    std::shared_ptr<CMosquittoManager> pmm, TASK_PARAMS *pdev_task)
{
    auto dev = pcm->get_terminal_device(pdev_task->dev_id);
    if (nullptr == dev){
        CLogger::getInstance()->LOG_W("不存在该设备:%lld", pdev_task->dev_id);
        return -1;;
    }

    auto protocol_rule = pcm->get_protocol_rule(dev->protocol_id);
    if (nullptr == protocol_rule) {
        CLogger::getInstance()->LOG_W("协议规则[%lld]为空", dev->protocol_id);
        return -1;
    }

    if (2 != protocol_rule->protocol_type)  //dlt645
    {
        CLogger::getInstance()->LOG_W("run_frozen_collect:protocol_type=%d not surport.", protocol_rule->protocol_type);
        return -1;
    }

    std::unordered_map<int, st_dlt645_frozen_param>   mpfrozen_params;  //冻结数据(含冻结时间DI及冻结数据DI)
    st_dlt645_loadrec_param  stfrozen_loadrec;              //给定块数的负荷记录
    st_dlt645_loadrec_param  stfrozen_loadrec_witchtime;    //给定块数和时间的负荷记录

    for (auto taskitem_id = pdev_task->items.begin(); taskitem_id != pdev_task->items.end(); taskitem_id++)
    {
        auto task_item = pcm->get_item(taskitem_id->item_id);
        if (nullptr == task_item){
            CLogger::getInstance()->log_w("不存在该任务项:%lld", taskitem_id->item_id);
            continue;
        }

        auto dlt645_fr_time = pcm->get_dlt645_freezetime(task_item->task_item_id);
        if (nullptr == dlt645_fr_time)
        {
            CLogger::getInstance()->LOG_W("run_frozen_collect:can't find frozen_time:%lld", task_item->task_item_id);
            continue;
        }

        auto dlt645_frozen_reqs = pcm->get_dlt645_freeze_requests();
        for (auto itr = dlt645_frozen_reqs->begin(); itr != dlt645_frozen_reqs->end(); itr++)
        {
            if (itr->second.freeze_time_id != dlt645_fr_time->id)
            {
                continue;
            }

            if (1 == dlt645_fr_time->type)  //1冻结数据  
            {
                auto  itp = mpfrozen_params.find(dlt645_fr_time->id);
                if (itp != mpfrozen_params.end())
                {
                    itp->second.lstdata_di.push_back(itr->second.di);
                }
                else
                {
                    st_dlt645_frozen_param  stfrozen_param;
                    stfrozen_param.dev_id = pdev_task->dev_id;
                    stfrozen_param.frozen_time_di = dlt645_fr_time->time_or_di;
                    stfrozen_param.protocol_id = dlt645_fr_time->protocol_id;
                    stfrozen_param.frozen_type = dlt645_fr_time->freeze_type;
                    stfrozen_param.lstdata_di.push_back(itr->second.di);
                    mpfrozen_params.insert(std::make_pair(dlt645_fr_time->id, stfrozen_param));
                }
            }
            else if (2 == dlt645_fr_time->type) //2负荷记录
            {
                st_loadrec_block  stblock;
                stblock.block_count = dlt645_fr_time->block_count;
                stblock.data_di = itr->second.di;

                if (dlt645_fr_time->time_or_di.empty()){
                    stfrozen_loadrec.frozen_type = dlt645_fr_time->freeze_type;
                    stfrozen_loadrec.freeze_interval = dlt645_fr_time->freeze_interval;
                    stfrozen_loadrec.lstdata_di.push_back(stblock);
                }
                else{
                    stfrozen_loadrec_witchtime.frozen_type = dlt645_fr_time->freeze_type;;
                    stfrozen_loadrec_witchtime.freeze_interval = dlt645_fr_time->freeze_interval;
                    stfrozen_loadrec_witchtime.lstdata_di.push_back(stblock);
                }
            }
            else{
                CLogger::getInstance()->log_w("dlt645 request type=%d no surport", dlt645_fr_time->type);
            }
        }
    }

    if (mpfrozen_params.size() > 0)
    {
        run_req_frozenitem(pcm, channel_ptr, pmm, dev, dev->protocol_id, mpfrozen_params);
    }
    else if (stfrozen_loadrec.lstdata_di.size() > 0)
    {
        stfrozen_loadrec.dev_id = dev->id;
        stfrozen_loadrec.protocol_id = dev->protocol_id;
        run_req_loadrec_item(pcm, channel_ptr, pmm, dev, pdev_task->task_id, stfrozen_loadrec, ENUM_FROZEN_TYPE_LOADREC);
    }
    else if (stfrozen_loadrec_witchtime.lstdata_di.size() > 0){
        stfrozen_loadrec_witchtime.dev_id = dev->id;
        stfrozen_loadrec_witchtime.protocol_id = dev->protocol_id;
        run_req_loadrec_item(pcm, channel_ptr, pmm, dev, pdev_task->task_id, stfrozen_loadrec_witchtime, ENUM_FROZEN_TYPE_LOADREC_T);
    }

    return 0;
}

int  CDlt645MessageManager::run_req_frozenitem(std::shared_ptr<CConfigManager> pcm,
    IChannel *channel_ptr,
    std::shared_ptr<CMosquittoManager> pmm,
    std::shared_ptr<TERMINAL_DEVICE> dev, int rule_id, std::unordered_map<int, st_dlt645_frozen_param> mpfrozen_params)
{
    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[16] = { 0 };
    int addr_len = 0, di_len = 0, frm_len = 0, rsp_len = 0;
    auto proto = pcm->get_protocol_rule(rule_id);
    if(nullptr == proto){
        return -1;
    }
    slave_addr_tobcd(dev->slave_addr, ucaddr, addr_len);
    if (6 > addr_len)
    {
        CLogger::getInstance()->log_w("run_req_frozenitem: dlt645 meter addr error.");
        return -1;
    }

    std::list<std::shared_ptr<st_dlt645_frozen_rspdata>>   lstfrozen_rspdata;
    for (auto itfp = mpfrozen_params.begin(); itfp != mpfrozen_params.end(); itfp++)
    {
        std::string  time_di = itfp->second.frozen_time_di;
        string_tobcd(time_di, ucdi, di_len);

        if (4 > di_len)
        {
            CLogger::getInstance()->log_w("run_req_frozenitem: di error.");
            continue;
        }

        std::shared_ptr<st_dlt645_frozen_rspdata> pfrozen_rspdata = std::make_shared<st_dlt645_frozen_rspdata>();
        pfrozen_rspdata->dev_id = dev->id;
        pfrozen_rspdata->rule_id = rule_id;
        pfrozen_rspdata->frozen_time_di = time_di;
        pfrozen_rspdata->frozen_type = itfp->second.frozen_type;
        pfrozen_rspdata->acq_start_time = get_timestamp();

        //冻结时间抄读
        CDlt645Frame::getIntanse()->packet_readingdata_req(ucaddr, ucdi, m_pdata, frm_len);
        if (frm_len > 0)
        {
            rsp_len = DLT645_FRMDATA_LEN;  //  >dlt645最大帧长
            channel_ptr->set_slave_addr(dev->slave_addr);
            channel_ptr->send_msg(m_pdata, frm_len, m_prspdata, rsp_len, proto->timeout);      
            OutputInfo(m_pdata, frm_len, true);
            if ((rsp_len > 0) && (DLT645_FRMDATA_LEN != rsp_len))
            {
                //待解析时间
                int start_pos = 0;
                int time_len = get_frmdata_len(m_prspdata, rsp_len, start_pos);
                pfrozen_rspdata->pfroken_time_data = new uint8_t[time_len];    //此处保存解析后得冻结时间---与抄读负荷记录对齐
                if (pfrozen_rspdata->pfroken_time_data)
                {
                    for (int i = 0; i < time_len; i++)
                    {
                        pfrozen_rspdata->pfroken_time_data[i] = m_prspdata[start_pos + time_len - 1 - i] - FLAG_ERRIDENT;
                    }
                    pfrozen_rspdata->time_len = time_len;
                }
                else{
                    CLogger::getInstance()->LOG_E("run_req_frozenitem,new memory error.");
                    return -1;
                }
            }
            else{
                CLogger::getInstance()->LOG_W("run_req_frozenitem,read frozen time error.");
                return -1;
            }
        }

        //冻结数据抄读
        for (auto itd = itfp->second.lstdata_di.begin(); itd != itfp->second.lstdata_di.end(); itd++)
        {
            std::string di = *itd;
            acq_frozendata_withdi(dev->slave_addr, channel_ptr, di, pfrozen_rspdata, nullptr, proto->timeout);
        }
        pfrozen_rspdata->acq_end_time = get_timestamp();
        lstfrozen_rspdata.push_back(pfrozen_rspdata);
    }

    //添加到解析线程池
    if (0 < lstfrozen_rspdata.size())
    {
        CDlt645FrozenDataParseTask*  pfrozen_parse_task = new CDlt645FrozenDataParseTask(pcm, pmm, lstfrozen_rspdata);
        if (pfrozen_parse_task)
        {
            m_thread_pool.add_task(pfrozen_parse_task);
        }
    }

    return 0;
}

int CDlt645MessageManager::run_req_loadrec_item(std::shared_ptr<CConfigManager> pcm, IChannel *channel_ptr,
    std::shared_ptr<CMosquittoManager> pmm, std::shared_ptr<TERMINAL_DEVICE> dev,
    int task_id, st_dlt645_loadrec_param stfrozen_loadrec, int item_type /* = ENUM_FROZEN_TYPE_LOADREC */)
{
    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[16] = { 0 };
    int addr_len = 0, di_len = 0;
    auto proto = pcm->get_protocol_rule(dev->protocol_id);
    if(nullptr == proto){
        return -1;
    }
    slave_addr_tobcd(dev->slave_addr, ucaddr, addr_len);
    if (6 > addr_len)
    {
        CLogger::getInstance()->log_w("run_req_frozenitem: dlt645 meteraddr error.");
        return -1;
    }

    std::shared_ptr<st_dlt645_frozen_rspdata> pfrozen_rspdata = std::make_shared<st_dlt645_frozen_rspdata>();
    pfrozen_rspdata->dev_id = dev->id;
    pfrozen_rspdata->rule_id = dev->protocol_id;
    pfrozen_rspdata->frozen_time_di = "";
    pfrozen_rspdata->frozen_type = stfrozen_loadrec.frozen_type;
    pfrozen_rspdata->acq_start_time = get_timestamp();

    //计算冻结时间，并添加到待解析结构体 冻结时间数据域中
    //ToDO:仅限帧格式2
    uint8_t ucdatetime[8] = { 0 };
    uint8_t bcd_datetime[8] = { 0 };

    get_frozen_time(ucdatetime, stfrozen_loadrec.freeze_interval);
    pfrozen_rspdata->pfroken_time_data = new uint8_t[5];
    if (!pfrozen_rspdata->pfroken_time_data){
        CLogger::getInstance()->log_w("acq_frozendata_withdi:new memory error.");
        return -1;
    }
    memcpy(pfrozen_rspdata->pfroken_time_data, ucdatetime, 5);
    pfrozen_rspdata->time_len = 5;
    deci_to_bcd(ucdatetime, bcd_datetime, 5);

    for (auto itf = stfrozen_loadrec.lstdata_di.begin(); itf != stfrozen_loadrec.lstdata_di.end(); itf++)
    {
        std::string di = itf->data_di;
        string_tobcd(di, ucdi, di_len);
        if (4 > di_len)
        {
            CLogger::getInstance()->log_w("run_req_loadrec_item:the dlt645 di error.");
            return -1;
        }

        if (item_type == ENUM_FROZEN_TYPE_LOADREC_T)
        {
            //负荷记录--带时间
            acq_frozendata_withdi(dev->slave_addr, channel_ptr, di, pfrozen_rspdata, bcd_datetime, itf->block_count, proto->timeout, 3);
        }
        else{
            //负荷记录--不带时间
            acq_frozendata_withdi(dev->slave_addr, channel_ptr, di, pfrozen_rspdata, bcd_datetime, itf->block_count, proto->timeout, 2);
        }

    }
    pfrozen_rspdata->acq_end_time = get_timestamp();

    //添加到解析任务线程池
    std::list<std::shared_ptr<st_dlt645_frozen_rspdata>>   lstfrozen_rspdata;
    lstfrozen_rspdata.push_back(pfrozen_rspdata);

    CDlt645FrozenDataParseTask* pfrozen_parse_task = new CDlt645FrozenDataParseTask(pcm, pmm, lstfrozen_rspdata);
    if (pfrozen_parse_task)
    {
        m_thread_pool.add_task(pfrozen_parse_task);
    }


    return 0;
}

int CDlt645MessageManager::acq_frozendata_withdi(std::string slave_addr, IChannel *channel_ptr, std::string di,
    std::shared_ptr<st_dlt645_frozen_rspdata> pfrozen_rspdata, uint8_t* pucdatetime, int timeout, uint8_t block_num, int frm_fmt)
{
    uint8_t ucaddr[16] = { 0 };
    uint8_t ucdi[16] = { 0 };

    int  addr_len = 0, di_len = 0, frm_len = 0, rsp_len = 0;

    slave_addr_tobcd(slave_addr, ucaddr, addr_len);
    string_tobcd(di, ucdi, di_len);

    if ((6 > addr_len) || (4 > di_len))
    {
        CLogger::getInstance()->log_w("acq_frozendata_withdi:the dlt645 meter addr or di error.");
        return -1;
    }

    st_frozen_dataitem  stfrozendata_item;
    stfrozendata_item.data_di = di;
    if (1 == frm_fmt){
        CDlt645Frame::getIntanse()->packet_readingdata_req(ucaddr, ucdi, m_pdata, frm_len);
    }
    else if (2 == frm_fmt){
        CDlt645Frame::getIntanse()->packet_readingdata_req(ucaddr, ucdi, block_num, m_pdata, frm_len);
    }
    else {
        CDlt645Frame::getIntanse()->packet_readingdata_req(ucaddr, ucdi, block_num, pucdatetime, m_pdata, frm_len);
    }

    if (frm_len > 0)
    {
        rsp_len = DLT645_FRMDATA_LEN;  //  >dlt645最大帧长
        channel_ptr->set_slave_addr(slave_addr);
        channel_ptr->send_msg(m_pdata, frm_len, m_prspdata, rsp_len, timeout);
        OutputInfo(m_pdata, frm_len, true);
        if ((rsp_len > 0) && (DLT645_FRMDATA_LEN != rsp_len))
        {
            st_frozen_frmdata  stfrozenfrm;
            stfrozenfrm.pfrozen_data = new uint8_t[rsp_len];
            memcpy(stfrozenfrm.pfrozen_data, m_prspdata, rsp_len);
            stfrozenfrm.data_len = rsp_len;

            stfrozendata_item.lstDataItem.push_back(stfrozenfrm);
            //粗解析数据，判断有无后续数据，若有，循环读取后续数据
            if (ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == get_ctrlcode(stfrozenfrm.pfrozen_data, rsp_len))
            {
                acq_frozen_subseqqdata(slave_addr, channel_ptr, ucdi, stfrozendata_item, timeout);
            }

            pfrozen_rspdata->lstfrozenDatas.push_back(stfrozendata_item);
        }
        else{
            CLogger::getInstance()->log_i("acq_frozendata_withdi: di=%s  Not recveived data .", di.c_str());
            return -1;
        }
    }

    return 0;
}

int CDlt645MessageManager::acq_frozen_subseqqdata(std::string slave_addr, IChannel *channel_ptr, uint8_t* pucdi, st_frozen_dataitem& stfrozendataitem, int timeout)
{
    uint8_t ucaddr[16] = { 0 };
    int  addr_len = 0, frm_len = 0, rsp_len = 0;

    slave_addr_tobcd(slave_addr, ucaddr, addr_len);
    if (6 > addr_len)
    {
        CLogger::getInstance()->log_w("acq_frozendata_withdi:the dlt645 meter addr error.");
        return -1;
    }

    uint8_t ctrl_code = 0;
    uint8_t seq_id = 1;
    while (seq_id <= 255) // 帧号最大255
    {
        CLogger::getInstance()->log_d("acq_frozen_subseqqdata:di=%02X%02X%02X%02X seq_id=%d", pucdi[0], pucdi[1], pucdi[2], pucdi[3], seq_id);

        frm_len = 0;
        CDlt645Frame::getIntanse()->packet_readingsubseqdata_req(ucaddr, pucdi, seq_id, m_pdata, frm_len);
        if (frm_len > 0)
        {
            rsp_len = DLT645_FRMDATA_LEN;  //  >645最大帧长
            channel_ptr->set_slave_addr(slave_addr);
            channel_ptr->send_msg(m_pdata, frm_len, m_prspdata, rsp_len);
            OutputInfo(m_pdata, frm_len);
            if ((rsp_len > 0) && (DLT645_FRMDATA_LEN != rsp_len))
            {
                OutputInfo(m_prspdata, rsp_len, false);

                st_frozen_frmdata  stfrozen_frmdata;
                stfrozen_frmdata.pfrozen_data = new uint8_t[rsp_len];
                if (stfrozen_frmdata.pfrozen_data)  {
                    memcpy(stfrozen_frmdata.pfrozen_data, m_prspdata, rsp_len);
                    stfrozen_frmdata.data_len = rsp_len;
                    stfrozendataitem.lstDataItem.push_back(stfrozen_frmdata);
                }
                else{
                    CLogger::getInstance()->LOG_E("acq_frozen_subseqqdata:new data pointer error.");
                    return -1;
                }

                ctrl_code = get_ctrlcode(m_prspdata, rsp_len);
                if (ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP == ctrl_code)
                {
                    seq_id++;
                }
                else if (ENUM_CTRLCODE_READ_SUBSEQDATA_RSP == ctrl_code)
                {
                    break;  //无后续数据，退出
                }
            }
            else{
                CLogger::getInstance()->log_w("acq_frozen_subseqqdata:HPLCProxy recv data is null.");
                return -1;
            }
        }
    }

    return 0;
}

int CDlt645MessageManager::get_frozen_time(uint8_t* pfrozentime, int freeze_interval/*分钟*/)
{
    memset(pfrozentime, 0, 5);
    if (freeze_interval >= 1440)  //日冻结
    {
        uint64_t  tnow = get_timestamp() - 86400 * 1000;  //昨日同时刻(ms)
        tnow /= 1000;
        time_t t = (time_t)tnow;
        struct tm * tm1 = localtime(&t);
        pfrozentime[0] = (tm1->tm_year + 1900) % 100;
        pfrozentime[1] = tm1->tm_mon + 1;
        pfrozentime[2] = tm1->tm_mday;
    }
    else if ((freeze_interval >= 60) && (freeze_interval < 1440)) //小时冻结
    {
        uint64_t  tnow = get_timestamp() - freeze_interval * 60 * 1000;  //上一个冻结时间(ms)
        tnow /= 1000;
        time_t t = (time_t)tnow;
        struct tm * tm1 = localtime(&t);
        pfrozentime[0] = (tm1->tm_year + 1900) % 100;
        pfrozentime[1] = tm1->tm_mon + 1;
        pfrozentime[2] = tm1->tm_mday;
        pfrozentime[3] = tm1->tm_hour;
    }
    else if ((freeze_interval >= 1) && (freeze_interval < 60))
    {
        uint64_t  tnow = get_timestamp() / 1000;
        uint64_t  tpre = tnow - 3600;  //上一个小时(ms)
        uint64_t  tfrozen = tpre;
        while (tpre < tnow)
        {
            tfrozen = tpre;
            tpre += freeze_interval * 60;
        }
        time_t t = (time_t)tfrozen;
        struct tm * tm1 = localtime(&t);
        pfrozentime[0] = (tm1->tm_year + 1900) % 100;
        pfrozentime[1] = tm1->tm_mon + 1;
        pfrozentime[2] = tm1->tm_mday;
        pfrozentime[3] = tm1->tm_hour;
        pfrozentime[4] = tm1->tm_min;
    }

    return 5;
}

void CDlt645MessageManager::deci_to_bcd(uint8_t* deci, uint8_t* bcd, int len)
{
    if ((nullptr == deci) || (nullptr == bcd)) {
        return;
    }

    for (int i = 0; i < len; i++) {
        bcd[i] = (deci[i] / 10) * 16 + (deci[i] % 10);
    }
}

int CDlt645MessageManager::packet_parent_frame(std::shared_ptr<CConfigManager> cm,
    std::shared_ptr<TERMINAL_DEVICE> pdev,
    uint8_t *data, int &len)
{
    if ((nullptr == cm) || (nullptr == pdev))
    {
        CLogger::getInstance()->log_w("packet_parent_frame：cm or pdev is null.");
        return -1;
    }

    std::string  slave_addr = pdev->slave_addr;
    uint8_t ucaddr[16] = { 0 };
    int  addr_len = 0;

    slave_addr_tobcd(slave_addr, ucaddr, addr_len);
    if (6 > addr_len)
    {
        CLogger::getInstance()->log_w("packet_parent_frame:the dlt645 meter addr error.");
        return -1;
    }

    uint8_t preq[128] = { 0 };
    int plen = 0;
    if (0 < CDlt645Frame::getIntanse()->packet_transmit_req(ucaddr, data, len, preq, plen)){
        memcpy(data, preq, plen);
        len = plen;
    }

    return len;
}

int CDlt645MessageManager::get_embeded_modbusdata(uint8_t* rsp, int rsplen, uint8_t* modbus_rsp, int& modbuslen)
{
    int prefix = verify_dlt645_frame(rsp, rsplen);
    if (0 > prefix)
    {
        CLogger::getInstance()->log_buf((const char*)rsp, rsplen);
        CLogger::getInstance()->log_w("collect_modbus_taskitem: dlt645frame error.%d", prefix);
        return 0;
    }

    uint8_t ctrlcode = rsp[prefix + 8];
    if (ctrlcode != ENUM_CTRLCODE_TRANSMIT_DATA_RSP)
    {
        CLogger::getInstance()->LOG_W("get_embeded_modbusdata: frame ctrlcode(%d) error.", ctrlcode);
        return 0;
    }

    int datalen = rsp[prefix + 9];
    if (rsplen < prefix + 9 + datalen)   //长度不正确
    {
        return 0;
    }
    datalen -= 1;  //减去转发类型1个字节

    uint8_t type = rsp[prefix + 10];
    if (1 != type)  //转发类型为1时为通过rs485转发
    {
        return 0;
    }
    for (int i = 0; i < datalen; i++)
    {
        modbus_rsp[i] = rsp[prefix + 11 + i] - FLAG_ERRIDENT;
    }
    modbuslen = datalen;

    CLogger::getInstance()->log_d("get_embeded_modbusdata datafield:");
    OutputInfo(modbus_rsp, datalen, false);

    return modbuslen;
}

//获取数据域中，数据的长
int CDlt645MessageManager::get_frmdata_len(uint8_t* pdata, int len, int& startpos)
{
    startpos = 0;
    int prefix_num = verify_dlt645_frame(pdata, len);
    if (prefix_num < 0)
    {
        return 0;
    }

    int data_len = 0;
    uint8_t ctrlcode = get_ctrlcode(pdata, len);
    if ((ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP == ctrlcode) || (ENUM_CTRLCODE_READ_METERDATA_RSP == ctrlcode)) {
        data_len = pdata[prefix_num + 9] - 4;  //减去数据标识长   
        startpos = prefix_num + 14;
    }
    else if ((ENUM_CTRLCODE_READ_SUBSEQDATA_RSP == ctrlcode) || (ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP == ctrlcode)) {
        data_len = pdata[prefix_num + 9] - 5;  //减去数据标识和帧序号长
        startpos = prefix_num + 14;
    }

    CLogger::getInstance()->log_d("CDlt645MessageManager::get_frmdata_len: len=%d", data_len);

    return data_len;
}

void CDlt645MessageManager::slave_addr_tobcd(std::string& slave_addr, uint8_t* pbcd, int& len)
{
    std::string dev_addr;
    if (slave_addr.length() > 12) {
        dev_addr = slave_addr.substr(0, 12);
    }
    else if (slave_addr.length() < 12) {
        dev_addr = std::string(12 - slave_addr.length(), '0') + slave_addr;
    }
    else{
        dev_addr = slave_addr;
    }

    string_tobcd(dev_addr, pbcd, len);
}